
using Nop.Core;
using Nop.Core.Caching;
using Nop.Core.Data;
using Nop.Core.Domain.XJ;
using Nop.Data;
using Nop.Services.Events;
using System;
using System.Collections.Generic;
using System.Linq;

namespace Nop.Services.XJ
{
	/// <summary>
	/// XJEquipmentStockInDetail service
	/// </summary>
	public partial class XJEquipmentStockInDetailService : IXJEquipmentStockInDetailService
	{
		#region Constants

		/// <summary>
		/// Key for caching
		/// </summary>
		private const string XJEQUIPMENTSTOCKINDETAILS_ALL_KEY = "Nop.xjequipmentstockindetail.all";
		/// <summary>
		/// Key for caching
		/// </summary>
		/// <remarks>
		/// {0} : xJEquipmentStockInDetail ID
		/// </remarks>
		private const string XJEQUIPMENTSTOCKINDETAIL_BY_ID_KEY = "Nop.xjequipmentstockindetail.id-{0}";
		/// <summary>
		/// Key pattern to clear cache
		/// </summary>
		private const string XJEQUIPMENTSTOCKINDETAILS_PATTERN_KEY = "Nop.xjequipmentstockindetail.";
		#endregion

		#region Fields
		private readonly IRepository<XJEquipmentStockInDetail> _xJEquipmentStockInDetailRepository;
		private readonly IRepository<XJEquipmentStockIn> _xJEquipmentStockInRepository;
		private readonly IRepository<XJEquipment> _xJEquipmentRepository;
		private readonly IDbContext _dbContext;
		private readonly IEventPublisher _eventPublisher;
		private readonly ICacheManager _cacheManager;
		#endregion

		#region Ctor

		/// <summary>
		/// Ctor
		/// </summary>
		/// <param name="cacheManager">Cache manager</param>
		/// <param name="xJEquipmentStockInDetailRepository">XJEquipmentStockInDetail repository</param>
		/// <param name="eventPublisher">Event published</param>
		public XJEquipmentStockInDetailService(ICacheManager cacheManager,
			IRepository<XJEquipmentStockInDetail> xJEquipmentStockInDetailRepository,
			IRepository<XJEquipmentStockIn> xJEquipmentStockInRepository,
			IRepository<XJEquipment> xJEquipmentRepository,
			IDbContext dbContext,
			IEventPublisher eventPublisher)
		{
			this._cacheManager = cacheManager;
			this._xJEquipmentStockInDetailRepository = xJEquipmentStockInDetailRepository;
			this._xJEquipmentStockInRepository = xJEquipmentStockInRepository;
			this._xJEquipmentRepository = xJEquipmentRepository;
			this._dbContext = dbContext;
			this._eventPublisher = eventPublisher;
		}

		#endregion

		#region Methods

		/// <summary>
		/// Gets all XJEquipmentStockInDetails
		/// </summary>
		/// <returns>XJEquipmentStockInDetails</returns>
		public virtual IList<XJEquipmentStockInDetail> GetAllXJEquipmentStockInDetails()
		{
			string key = XJEQUIPMENTSTOCKINDETAILS_ALL_KEY;
			return _cacheManager.Get(key, () =>
			{
				var query = from a in _xJEquipmentStockInDetailRepository.Table
							orderby a.Id
							select a;
				return query.ToList();
			});
		}

		public virtual IPagedList<XJEquipmentStockInDetail> GetAllStockInDetails(int inId, int pageIndex = 0, int pageSize = int.MaxValue)
		{
			var query = _xJEquipmentStockInDetailRepository.Table;
			if (inId > 0)
				query = query.Where(m => m.EquipmentStockInId == inId);
			query = query.OrderByDescending(c => c.Id);

			//paging
			return new PagedList<XJEquipmentStockInDetail>(query, pageIndex, pageSize);
		}

		public virtual IPagedList<XJEquipmentStockInDetailTemp> GetEquipmentStockInDetails(
			int equipmentId = 0,
			string sno = "",
			string name = "",
			DateTime? startOn = null,
			DateTime? endOn = null,
			int departmentId = 0,
			int customerId = 0,
			int minState = 0,
			int state = 0,
			int pageIndex = 0,
			int pageSize = int.MaxValue
			)
		{
			var query = from x in _xJEquipmentStockInDetailRepository.Table
						join y in _xJEquipmentStockInRepository.Table on x.EquipmentStockInId equals y.Id
						join z in _xJEquipmentRepository.Table on x.EquipmentId equals z.Id
						select new XJEquipmentStockInDetailTemp
						{
							Id = x.Id,
							SNo = y.SNo,
							State = y.State,
							DepartmentId = y.DepartmentId,
							DepartmentName = y.DepartmentName,
							CustomerId = y.CustomerId,
							CustomerName = y.CustomerName,
							CreatedOn = y.CreatedOn,
							Reviewer = y.Reviewer,
							ReviewOn = y.ReviewOn,
							EquipmentStockInId = x.EquipmentStockInId,
							EquipmentId = x.EquipmentId,
							Name = x.Name,
							Manufacturer = x.Manufacturer,
							Specification = x.Specification,
							Unit = z.Unit ?? "",
							Price = x.Price,
							Amount = x.Amount,
						};
			if (equipmentId > 0)
				query = query.Where(m => m.EquipmentId == equipmentId);
			if (departmentId > 0)
				query = query.Where(m => m.DepartmentId == departmentId);
			if (customerId > 0)
				query = query.Where(m => m.CustomerId == customerId);
			if (!string.IsNullOrEmpty(sno))
				query = query.Where(m => m.SNo.Contains(sno));
			if (!string.IsNullOrEmpty(name))
				query = query.Where(m => m.Name.Contains(name));
			if (startOn.HasValue)
				query = query.Where(m => m.CreatedOn >= startOn.Value);
			if (endOn.HasValue)
			{
				DateTime end = endOn.Value.AddDays(1);
				query = query.Where(m => m.CreatedOn < end);
			}
			if (state > 0)
				query = query.Where(m => m.State == state);
			query = query.OrderByDescending(c => c.Id);

			//paging
			return new PagedList<XJEquipmentStockInDetailTemp>(query, pageIndex, pageSize);
		}

		public virtual StockInTotal GetTotal(
			int equipmentId = 0,
			string sno = "",
			string name = "",
			DateTime? startOn = null,
			DateTime? endOn = null,
			int departmentId = 0,
			int customerId = 0,
			int minState = 0,
			int state = 0
			)
		{
			string strSqlSearch = string.Empty;
			if (equipmentId > 0)
				strSqlSearch += string.Format(" AND sod.EquipmentId = {0}", equipmentId);
			if (departmentId > 0)
				strSqlSearch += string.Format(" AND so.DepartmentId = {0}", departmentId);
			if (customerId > 0)
				strSqlSearch += string.Format(" AND so.CustomerId = {0}", customerId);
			if (!string.IsNullOrEmpty(sno))
				strSqlSearch += string.Format(" AND so.SNo LIKE '%{0}%'", sno);
			if (!string.IsNullOrEmpty(name))
				strSqlSearch += string.Format(" AND sod.Name LIKE '%{0}%'", name);
			if (startOn.HasValue)
				strSqlSearch += string.Format(" AND so.CreatedOn >= '{0}'", startOn.Value.ToString("yyyyy-MM-dd"));
			if (endOn.HasValue)
			{
				DateTime end = endOn.Value.AddDays(1);
				strSqlSearch += string.Format(" AND so.CreatedOn < '{0}'", endOn.Value.ToString("yyyyy-MM-dd"));
			}
			if (state > 0)
				strSqlSearch += string.Format(" AND so.State = {0}", state);
			string strSql = string.Format(@"SELECT SUM(sod.Amount*sod.Price) AS Total FROM XJEquipmentStockInDetail sod
						INNER JOIN XJEquipmentStockIn so ON sod.EquipmentStockInId = so.Id
						INNER JOIN XJEquipment e ON sod.EquipmentId = e.Id
						WHERE 1=1{0}"
			, strSqlSearch);

			try
			{
				var query = _dbContext.SqlQuery<StockInTotal>(strSql).FirstOrDefault();
				return query;
			}
			catch (Exception)
			{
				return new StockInTotal();
			}
		}

		public virtual int[] GetEquipmentIds(int stockInId)
		{
			var details = GetAllStockInDetails(stockInId);
			return details.Select(x => x.EquipmentId).ToArray();
		}

		/// <summary>
		/// Gets a XJEquipmentStockInDetail 
		/// </summary>
		/// <param name="xJEquipmentStockInDetailId">XJEquipmentStockInDetail identifier</param>
		/// <returns>XJEquipmentStockInDetail</returns>
		public virtual XJEquipmentStockInDetail GetXJEquipmentStockInDetailById(int xJEquipmentStockInDetailId)
		{
			if (xJEquipmentStockInDetailId == 0)
				return null;

			string key = string.Format(XJEQUIPMENTSTOCKINDETAIL_BY_ID_KEY, xJEquipmentStockInDetailId);
			return _cacheManager.Get(key, () => _xJEquipmentStockInDetailRepository.GetById(xJEquipmentStockInDetailId));
		}

		public virtual XJEquipmentStockInDetail GetXJEquipmentStockInDetailByInIdAndEId(int stockInId, int equipmentId)
		{
			return _xJEquipmentStockInDetailRepository.Table.FirstOrDefault(m => m.EquipmentStockInId == stockInId && m.EquipmentId == equipmentId);
		}

		/// <summary>
		/// Inserts a XJEquipmentStockInDetail
		/// </summary>
		/// <param name="xJEquipmentStockInDetail">XJEquipmentStockInDetail</param>
		public virtual void InsertXJEquipmentStockInDetail(XJEquipmentStockInDetail xJEquipmentStockInDetail)
		{
			if (xJEquipmentStockInDetail == null)
				throw new ArgumentNullException("xJEquipmentStockInDetail");

			_xJEquipmentStockInDetailRepository.Insert(xJEquipmentStockInDetail);

			_cacheManager.RemoveByPattern(XJEQUIPMENTSTOCKINDETAILS_PATTERN_KEY);

			//event notification
			_eventPublisher.EntityInserted(xJEquipmentStockInDetail);
		}

		/// <summary>
		/// Updates the XJEquipmentStockInDetail
		/// </summary>
		/// <param name="xJEquipmentStockInDetail">XJEquipmentStockInDetail</param>
		public virtual void UpdateXJEquipmentStockInDetail(XJEquipmentStockInDetail xJEquipmentStockInDetail)
		{
			if (xJEquipmentStockInDetail == null)
				throw new ArgumentNullException("xJEquipmentStockInDetail");

			_xJEquipmentStockInDetailRepository.Update(xJEquipmentStockInDetail);

			_cacheManager.RemoveByPattern(XJEQUIPMENTSTOCKINDETAILS_PATTERN_KEY);

			//event notification
			_eventPublisher.EntityUpdated(xJEquipmentStockInDetail);
		}

		/// <summary>
		/// Deletes a XJEquipmentStockInDetail
		/// </summary>
		/// <param name="xJEquipmentStockInDetail">XJEquipmentStockInDetail</param>
		public virtual void DeleteXJEquipmentStockInDetail(XJEquipmentStockInDetail xJEquipmentStockInDetail)
		{
			if (xJEquipmentStockInDetail == null)
				throw new ArgumentNullException("xJEquipmentStockInDetail");

			_xJEquipmentStockInDetailRepository.Delete(xJEquipmentStockInDetail);

			_cacheManager.RemoveByPattern(XJEQUIPMENTSTOCKINDETAILS_PATTERN_KEY);

			//event notification
			_eventPublisher.EntityDeleted(xJEquipmentStockInDetail);
		}

		#endregion
	}
}
